Repository navigation
build: install libe3 like a regular library, publish the binding as libe3py (0.2.3) - #125
Merged
Merged
Conversation
`build_libe3 --install --enable-swig` installed the Python module into the site-packages of whatever interpreter CMake found, regardless of --prefix: the system one unless the right venv was active. Without root that install failed, and because the module's rules ran before the library's own, the failure stopped the install before liblibe3, the headers and libe3.pc were written; consumers then reported "Package 'libe3' not found". A library install now writes only the library. `cmake --install` installs the module only when -DLIBE3_PYTHON_INSTALL_DIR is given (CI's staged install keeps working), and its rules are included after libe3Install, so they cannot stop the library install. The binding is meant to be installed with pip, built against the installed library (next commit). The SWIG module definition moves to cmake/libe3SwigModule.cmake so the in-tree build and the pip build compile it the same way; it links Python3::Module (not libpython) when CMake has it. build_libe3: - --all-encodings enables ASN.1, JSON and Protocol Buffers, what a gNB needs to serve any dApp; - --install uses sudo only when the prefix is not writable, refreshes the linker cache after an install into /usr or /usr/local, and prints the PKG_CONFIG_PATH line for any other prefix; - the CMake check runs after --install-deps, which is what installs CMake on a fresh machine: before, `./build_libe3 -I` stopped with "CMake is required" on exactly the machine it is meant for. The README gives one install recipe, the one OAI and the dApp library point to. Checked in a fresh ubuntu:24.04 container as a user with sudo: -I on a machine without CMake, --all-encodings --install into /usr/local (one sudo, ldconfig run), pkg-config and find_package find it with no environment variable, nothing is written into any Python site-packages, and the in-tree --enable-swig build passes `ctest -L swig`. Assisted-by: Claude:claude-opus-5-5
…ibe3 The Python binding could only be had by building libe3 with SWIG and installing it into the right interpreter. It is now a package, libe3py, that pip builds against the libe3 installed on the machine, in any virtual environment and without root: ./build_libe3 --all-encodings --install # once, sudo pip install libe3py # or pip install . from a checkout - pyproject.toml (scikit-build-core) takes its version from VERSION and builds python/CMakeLists.txt; the sdist carries only the SWIG sources, the shared module definition and the license files. - python/CMakeLists.txt finds the installed library with find_package(libe3 CONFIG), so the module links libe3 statically as before, with the feature macros (encodings, latrec) libe3 was built with, and needs no liblibe3.so at run time. It stops unless the installed libe3 is the same version as the package, which keeps library and binding in step. - tag-and-release builds the sdist on every release, publishes it to PyPI and then TestPyPI (trusted publishing, environments pypi and testpypi, as the dApp library does), and attaches it to the GitHub release. sdist only: a plain linux_x86_64 wheel is rejected by PyPI. - pr-tests' swig job pip-installs the sdist against its staged install and runs the smoke test on the result. Checked in a fresh ubuntu:24.04 container: the sdist builds; pip installs it in a venv without sudo against libe3 in /usr/local; the module has no liblibe3 or libpython run-time dependency; tests/test_swig_smoke.py passes on it; `pip install .` from the checkout works; a package of another version is refused with the mismatch message. actionlint reports nothing new on either workflow. Not checked: the publishing jobs (they need a release), and a libe3 outside the standard prefixes through CMAKE_PREFIX_PATH (CI covers it). Assisted-by: Claude:claude-opus-5-5
libe3 is installed as a regular library and its Python binding is the libe3py package on PyPI, built against it; build_libe3 -I works on a machine without CMake. Assisted-by: Claude:claude-opus-5-5
Thecave3
force-pushed
the
fix/python-install-prefix
branch
from
October 10, 2026 15:03
9bbce95 to
3ce706c
Compare
Contributor
CI report —
|
| Workflow | Result | Time | Run |
|---|---|---|---|
| Commit policy | ✅ success | 2m32s | #135 |
| E2E dApp Integration | ✅ success | 1m58s | #140 |
| E2E Topologies (multi-dApp / multi-RAN) | ✅ success | 2m12s | #138 |
| Full-loop Latency Benchmark | ✅ success | 1m02s | #139 |
| Unit Tests | ✅ success | 4m22s | #166 |
| latrec portability | ⏭️ not triggered (paths filter) | — | — |
| MPMC Queue Benchmark | ⏭️ not triggered (paths filter) | — | — |
E2E Topologies (multi-dApp / multi-RAN)
zmq/ipc
- ✅ 1 RAN - 1 dApp: indications=
5dapppeer=t11 ran=ran-solo sub=1 indications=5 seq=[0..4] dropped=0 (0%) age_ms(avg=0 max=0 @seq=0) hist[<=1:5 2-5:0 6-10:0 >10:0]
- ✅ 1 RAN - 2 dApps: dApp#1 ind=
5sub=1, dApp#2 ind=6sub=2, RAN saw2dApps - ✅ 2 RANs - 1 dApp: from ran-a ind=
5, from ran-b ind=5
zmq/tcp
- ✅ 1 RAN - 1 dApp: indications=
5dapppeer=default ran=ran-solo sub=1 indications=5 seq=[0..4] dropped=0 (0%) age_ms(avg=0 max=0 @seq=0) hist[<=1:5 2-5:0 6-10:0 >10:0]
- ✅ 1 RAN - 2 dApps: dApp#1 ind=
5sub=1, dApp#2 ind=6sub=2, RAN saw2dApps - ✅ 2 RANs - 1 dApp: from ran-a ind=
5, from ran-b ind=5
E2E dApp Integration
✅ posix/ipc
- dApp exit:
0 - Indications received:
7
✅ posix/tcp
- dApp exit:
0 - Indications received:
7
✅ zmq/ipc
- dApp exit:
0 - Indications received:
7
✅ zmq/tcp
- dApp exit:
0 - Indications received:
7
Full-loop Latency Benchmark
Full-loop latency
Full-loop latency benchmark (N=1023 after 50 warmup)
All values in microseconds (μs). Link: zmq, transport: ipc, encoding: ASN.1 APER.
| # | Description | Tags | mean | p50 | p99 | max |
|---|---|---|---|---|---|---|
| 1 | Collect indication data | RECORD_BEGIN to ENCODE_E3SM_BEGIN |
0.12 | 0.11 | 0.35 | 0.62 |
| 2 | Create & encode indication | ENCODE_E3SM_BEGIN to ENCODE_E3SM_DONE |
1.02 | 1.00 | 1.43 | 19.49 |
| 3 | Encode E3AP (indication) | EMIT_ENTER to ENQUEUE, then DEQUEUE to ENCODE_E3AP_DONE |
3.08 | 3.04 | 5.65 | 5.91 |
| 4 | Queuing (indication) | ENQUEUE to DEQUEUE |
5.50 | 5.63 | 14.73 | 26.85 |
| 5 | Delivery (indication) | ENCODE_E3AP_DONE to SEND_DONE |
0.32 | 0.27 | 0.56 | 8.60 |
| 6 | E3 wire (RAN -> dApp) | SEND_DONE to RECV |
51.17 | 51.61 | 65.18 | 132.00 |
| 7 | Decode E3AP (indication) | RECV to DECODE_E3AP_DONE |
1.76 | 1.50 | 5.74 | 11.19 |
| 8 | libe3 dispatch (indication) | DECODE_E3AP_DONE to DELIVER_BEGIN |
0.12 | 0.13 | 0.17 | 0.22 |
| 9 | Decode indication | DELIVER_BEGIN to DECODE_E3SM_DONE |
0.71 | 0.66 | 0.96 | 1.28 |
| 10 | Process data | DECODE_E3SM_DONE to ENCODE_E3SM_BEGIN |
0.04 | 0.04 | 0.05 | 0.07 |
| 11 | Create & encode control | ENCODE_E3SM_BEGIN to ENCODE_E3SM_DONE |
0.37 | 0.35 | 0.54 | 0.72 |
| 12 | Encode E3AP (control) | EMIT_ENTER to ENQUEUE, then DEQUEUE to ENCODE_E3AP_DONE |
3.55 | 3.53 | 5.03 | 6.20 |
| 13 | Queuing (control) | ENQUEUE to DEQUEUE |
16.06 | 15.94 | 25.94 | 283.50 |
| 14 | Delivery (control) | ENCODE_E3AP_DONE to SEND_DONE |
5.28 | 5.14 | 8.16 | 10.18 |
| 15 | E3 wire (dApp -> RAN) | SEND_DONE to RECV |
51.42 | 51.92 | 63.38 | 107.69 |
| 16 | Decode E3AP (control) | RECV to DECODE_E3AP_DONE |
2.77 | 2.58 | 5.99 | 18.42 |
| 17 | libe3 dispatch (control) | DECODE_E3AP_DONE to DECODE_E3SM_BEGIN |
0.26 | 0.26 | 0.39 | 1.90 |
| 18 | Decode & handle control | DECODE_E3SM_BEGIN to DECODE_E3SM_DONE |
0.37 | 0.34 | 0.57 | 0.72 |
| Total | Total round-trip | 144.42 | 144.65 | 178.25 | 451.50 |
ubuntu-latest, Release build, ZMQ + IPC, ASN.1 APER.
These numbers are measured inside a GitHub Actions container and should be treated as an upper bound on E3AP's and the library's own latency, not a representative deployment measurement.
Ready to merge (fast-forward only)
A maintainer can land the reviewed commits with:
git fetch origin
git checkout main && git merge --ff-only 416c7d079aebca79cc143030ce0d3e4c367c9628 && git push origin mainHead: 416c7d079aebca79cc143030ce0d3e4c367c9628 (branch fix/python-install-prefix). If --ff-only fails as non-fast-forward, the branch must be rebased on the latest main.
One comment per PR, rewritten in place once every workflow for
416c7d0finished.
…cks to CI The template asked contributors to tick a mandatory test checklist, a CI checklist and a workflow confirmation. Every box restates something CI already enforces and reports in the single CI report comment (Release and Debug builds and tests, the benchmark, the commit policy: trailers, linear history, per-commit builds, SPDX), so the boxes added work without adding a check. Keep the summary, the type of change, the linked issue and the twin-repo coordination, and say in CONTRIBUTING that CI is what checks. Assisted-by: Claude:claude-opus-5-5
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
./build_libe3 --all-encodings --installputs libe3 into/usr/localwith a singlesudo, refreshes the linker cache, and writes nothing into any Python site-packages. Before,--install --enable-swigcopied the Python module into the systemdist-packageswhenever the right venv was not active; without root that failed, and because the module's install rules ran before the library's, it stopped the install beforeliblibe3, the headers andlibe3.pcwere written, so consumers then reportedPackage 'libe3' not found.libe3py, built against the installed libe3 (find_package(libe3 CONFIG), static link as before, same feature macros) and refusing an installed libe3 of another version. Every release now publishes its sdist to PyPI and then TestPyPI (trusted publishing, environmentspypi/testpypi, as the dApp library does) and attaches it to the GitHub release. The dApp library will depend on it, sopip install dappsbrings it in.build_libe3:--all-encodings(ASN.1, JSON, Protocol Buffers),--installusessudoonly when the prefix is not writable, and-Inow works on a machine without CMake (the CMake check ran before the dependencies were installed).VERSION0.2.2 -> 0.2.3.Type of change
Linked issue
No tracking issue; this PR is the record of the change.
Mandatory test checklist
./build_libe3 -c -d build -j $(nproc) -r -tpasses (Release build + tests): left to CI./build_libe3 -c -d build -j $(nproc) -g -tpasses (Debug build + tests): left to CIcd build && ctest --output-on-failureis clean: left to CImpmc_queue.hppis untouchedVERSIONbumped per SemVer (0.2.3; no API or ABI change, packaging and install behaviour change)include/: none touched./build_libe3 -I(none added;-Iitself fixed)libe3.pcinterface: unchanged;dApp-openairinterface5gconfigures and builds against the/usr/localinstall with noPKG_CONFIG_PATH(Found libe3, version 0.2.3, encodingsasn1;json;protobuf)Checked in a fresh
ubuntu:24.04container as a non-root user with sudo:./build_libe3 -Ion a machine without CMake, then./build_libe3 --all-encodings --install: onesudo,ldconfigrun,pkg-config --modversion libe3andfind_package(libe3)work with no environment variable, nothing written to any Python site-packages;python -m build --sdist, thenpip install dist/libe3py-*.tar.gzin a venv withoutsudo: the module has noliblibe3orlibpythonrun-time dependency andtests/test_swig_smoke.pypasses on it;pip install .from the checkout works; a package whose version differs from the installed libe3 is refused with the mismatch message;--enable-swigbuild passesctest -L swig.Also used end to end: the dApp library pip-installs
libe3py0.2.3 against it (its test suite passes,libe3pytests no longer skipped), and an OAI gNB built against it serves a dApp in an RF simulator setup with a UE.scripts/check_commit_trailers.py --base origin/main --head HEADis clean;actionlintreports nothing new on the two edited workflows.Not checked: the publishing jobs (they only run on a release), the root install itself outside the container, macOS, and the Debian package build.
CI checklist
Unit Testsis green (Debug + Release matrix onubuntu-latest)Commit policyis green (trailers + linear history + each commit builds/tests independently)MPMC Queue Benchmark: not applicableTwin-repo coordination
Paired PR(s): the dApp library will add the
libe3py>=0.2.3,<0.3dependency once 0.2.3 is published; the OAI E3 image moves to 0.2.3 with--all-encodingsindApp-openairinterface5g.Workflow confirmation
main(rebased ifmainmoved), with no merge commits.git bisect-safe): left to theCommit policyworkflow; the head was tested as above.CONTRIBUTING.md.